from copy import copy

class xlist(list):
    """An auto-extending list.
    
    If one sets an element of list at an index beyond the length of list,
    entries up to index are added automatically, filled up with placeholder."""
    def __init__(self, placeholder = None, *args):
        list.__init__(self, *args)
        self.placeholder = placeholder
        
    def __setitem__(self, index, arg):
        if isinstance(index, int) and index >= len(self):
            for i in range(index - len(self)):
                self.append(self.placeholder)
                
            self.append(arg)
            
        elif arg == None:
            pass
        else:
            list.__setitem__(self,index,arg)


class curry():
    def __init__(self, function, argl = None, argd = None):
        __setfunction__(self, function, argl, argd)
        
    def __setfunction__(self, function, argl = None, argd = None):
        self.function = function
        
        self.arbitrary_args = function.func_code.co_flags & 0x04
        self.arbitrary_keyw = function.func_code.co_flags & 0x08
        
        
        # mash-up old & new arguments
        if self.argl and argl:
            for e in xrange self.argl:
                if e is not curry
        tp = [e is not curry.PLACEHOLDER for e in self.argl or []]
        targl = [ self.argl[i] if tp[i] ]
        targd = self.argd

        if self.arbitrary_args:
            if argl == None:
                
                self.argl = xlist(curry.PLACEHOLDER)
                
                for i in range(len(targl)):
                    self[i] = targl[i]
            else:
                self.argl = argl

            
    
    def __call__(self, *argl, **argd):
        targl = copy(self.argl)
        targd = copy(self.argd)
        
        targl.extend(argl)
        targd.update(argd)
        
        argc = function.func_code.co_argcount
        if argc <= len(targl) and not curry.PLACEHOLDER in targl[:len(argc)]:
            return self.function(*targl, **targd)
        else:
            return curry(self.function, targl, targd)
    
    def __getitem__(self, index):
        result = self.__class__(self.function, copy(argl), copy(argd))
        if isinstance(index, slice):
            result.__putslice__(index)
            return result
            
        elif isinstance(index, tuple):
            
            for i in index:
                result.__putslice__(i)
            
            return result
        
        elif isinstance(index, int):
            return argl[index]
        
        elif isinstance(index, str):
            return argd[index]
        
        else:
            # todo: error handling
            pass
        
    def __putslice__(self, slice):
        if isinstance(index.start, int):
            self.argl[index.start] = index.stop
        elif isinstance(index.start, str):
            self.argd[index.start] = index.stop
        
        else:
            # todo: error handling
